/* eslint-disable prefer-rest-params */
const { BrowserWindow } = require('electron');
const util = require('../util');
const ipc = require('../ipc/main');
const windowCenterInstance = require('../windowCenter/main');
const Events = require('events');
const { merge } = require('lodash-es');
const windowEvents = [
  'close',
  'closed',
  'session-end',
  'unresponsive',
  'responsive',
  'blur',
  'focus',
  'show',
  'hide',
  'ready-to-show',
  'maximize',
  'unmaximize',
  'minimize',
  'restore',
  'will-resize',
  'resize',
  'will-move',
  'move',
  'moved',
  'enter-full-screen',
  'leave-full-screen',
  'enter-html-full-screen',
  'leave-html-full-screen',
  'always-on-top-changed',
  'app-command',
  'scroll-touch-begin',
  'scroll-touch-end',
  'scroll-touch-edge',
  'swipe',
  'rotate-gesture',
  'sheet-begin',
  'sheet-end',
  'new-window-for-tab',
];
// 窗体默认属性
const defaultOption = {
  webPreferences: {
    nodeIntegration: true,
    enableRemoteModule: true,
    contextIsolation: false,
    // 想使用preload.js下面的脚本必须得打开
    // contextIsolation: true,
  },
};

class BaseWindow extends Events {
  // 设置所有窗口默认属性
  static setDefaultOption(option) {
    // Object.assign(defaultOption, option);
    merge(defaultOption, option);
  }

  /**
   * @param { string } name - 窗体id/名称
   * @param { Electron.BrowserWindowConstructorOptions } option
   */
  constructor(name, option = {}) {
    super();
    if (util.isBoolean(name) === false) {
      throw new Error('process name cannot be null');
    }
    /**
     *
     * @type { Electron.BrowserWindow & { windowId: string } | any }
     */
    this.instance = null;
    this.name = name;
    this.option = option;
    // 注册到窗口中心
    windowCenterInstance._register(name, this);
  }

  /**
   * @typedef { Object | Electron.BrowserWindowConstructorOptions } OpenOptions
   * @property { string } url
   * @returns { Electron.BrowserWindow }
   */

  /**
   * open才会真正创建window窗体 返回其窗体实例
   * 重复创建相同的窗体 返回同一个实例
   * @param {OpenOptions} option
   */
  async open(option = {}) {
    try {
      if (this.instance === null) {
        // const _option = Object.assign({}, defaultOption, this.option, option);
        const _option = merge({}, defaultOption, this.option, option);
        this.instance = new BrowserWindow(_option);
        // 窗口ID，必须
        this.instance.windowId = this.name;
        // 注册进程服务 以键值对的形式存储创建的窗口实例
        ipc._register(this.name, this.instance);
        windowEvents.forEach(eventName => {
          this.instance.on(eventName, () => {
            // 广播窗口消息
            this.publisher(eventName, { ...arguments });
            if (eventName === 'closed') {
              this.instance = null;
              ipc._unregister(this.name);
            }
          });
        });
        await this.instance.loadURL(_option.url);
      }
    } catch (error) {
      console.error(error);
    }
    return this.instance;
  }

  // 判断窗口实例是否存在
  isInstanceExist() {
    return !!this.instance;
  }

  getInstance() {
    return this.instance;
  }

  // 发布通知
  publisher(eventName, params = {}) {
    ipc._publisher({ header: { fromId: this.name, eventName }, body: params });
    this.emit(eventName, params);
  }

  request(eventName = '', data = {}, timeout) {
    return ipc.request(this.name, eventName, data, timeout);
  }

  subscribe(eventName = '', callback) {
    return ipc.subscribe(this.name, eventName, callback);
  }

  unsubscribe(eventName, callback) {
    return ipc.unsubscribe(this.name, eventName, callback);
  }
}

module.exports = BaseWindow;
